import { ref, onMounted, onUnmounted } from 'vue'

export interface PerformanceMetrics {
  loadTime: number
  domContentLoaded: number
  firstPaint: number
  firstContentfulPaint: number
  largestContentfulPaint: number
  firstInputDelay: number
  cumulativeLayoutShift: number
  memoryUsage?: {
    usedJSHeapSize: number
    totalJSHeapSize: number
    jsHeapSizeLimit: number
  }
}

export function usePerformance() {
  const metrics = ref<Partial<PerformanceMetrics>>({})
  const isSupported = ref(false)

  const getNavigationTiming = () => {
    if (!performance.timing) return

    const timing = performance.timing
    metrics.value.loadTime = timing.loadEventEnd - timing.navigationStart
    metrics.value.domContentLoaded = timing.domContentLoadedEventEnd - timing.navigationStart
  }

  const getPaintTiming = () => {
    if (!performance.getEntriesByType) return

    const paintEntries = performance.getEntriesByType('paint')
    paintEntries.forEach((entry) => {
      if (entry.name === 'first-paint') {
        metrics.value.firstPaint = entry.startTime
      } else if (entry.name === 'first-contentful-paint') {
        metrics.value.firstContentfulPaint = entry.startTime
      }
    })
  }

  const getLargestContentfulPaint = () => {
    if (!('PerformanceObserver' in window)) return

    try {
      const observer = new PerformanceObserver((list) => {
        const entries = list.getEntries()
        const lastEntry = entries[entries.length - 1]
        if (lastEntry) {
          metrics.value.largestContentfulPaint = lastEntry.startTime
        }
      })
      observer.observe({ entryTypes: ['largest-contentful-paint'] })
    } catch (error) {
      console.warn('LCP observation failed:', error)
    }
  }

  const getFirstInputDelay = () => {
    if (!('PerformanceObserver' in window)) return

    try {
      const observer = new PerformanceObserver((list) => {
        const entries = list.getEntries()
        entries.forEach((entry: any) => {
          if (entry.processingStart && entry.startTime) {
            metrics.value.firstInputDelay = entry.processingStart - entry.startTime
          }
        })
      })
      observer.observe({ entryTypes: ['first-input'] })
    } catch (error) {
      console.warn('FID observation failed:', error)
    }
  }

  const getCumulativeLayoutShift = () => {
    if (!('PerformanceObserver' in window)) return

    try {
      let clsValue = 0
      const observer = new PerformanceObserver((list) => {
        const entries = list.getEntries()
        entries.forEach((entry: any) => {
          if (!entry.hadRecentInput) {
            clsValue += entry.value
            metrics.value.cumulativeLayoutShift = clsValue
          }
        })
      })
      observer.observe({ entryTypes: ['layout-shift'] })
    } catch (error) {
      console.warn('CLS observation failed:', error)
    }
  }

  const getMemoryUsage = () => {
    if ('memory' in performance) {
      const memory = (performance as any).memory
      metrics.value.memoryUsage = {
        usedJSHeapSize: memory.usedJSHeapSize,
        totalJSHeapSize: memory.totalJSHeapSize,
        jsHeapSizeLimit: memory.jsHeapSizeLimit
      }
    }
  }

  const measureApiCall = async <T>(
    apiCall: () => Promise<T>,
    apiName: string
  ): Promise<T> => {
    const startTime = performance.now()
    try {
      const result = await apiCall()
      const endTime = performance.now()
      const duration = endTime - startTime
      
      console.log(`[Performance] API ${apiName} took ${duration.toFixed(2)}ms`)
      
      return result
    } catch (error) {
      const endTime = performance.now()
      const duration = endTime - startTime
      console.error(`[Performance] API ${apiName} failed after ${duration.toFixed(2)}ms`, error)
      throw error
    }
  }

  const measureComponentRender = (componentName: string) => {
    const startTime = performance.now()
    
    return () => {
      const endTime = performance.now()
      const duration = endTime - startTime
      console.log(`[Performance] Component ${componentName} rendered in ${duration.toFixed(2)}ms`)
    }
  }

  const logMetrics = () => {
    console.group('Performance Metrics')
    console.table(metrics.value)
    console.groupEnd()
  }

  const init = () => {
    isSupported.value = 'performance' in window

    if (!isSupported.value) {
      console.warn('Performance API is not supported')
      return
    }

    // 等待页面加载完成后收集指标
    if (document.readyState === 'complete') {
      getNavigationTiming()
      getPaintTiming()
      getMemoryUsage()
    } else {
      window.addEventListener('load', () => {
        setTimeout(() => {
          getNavigationTiming()
          getPaintTiming()
          getMemoryUsage()
        }, 0)
      })
    }

    // 观察 Web Vitals
    getLargestContentfulPaint()
    getFirstInputDelay()
    getCumulativeLayoutShift()
  }

  onMounted(() => {
    init()
  })

  return {
    metrics,
    isSupported,
    measureApiCall,
    measureComponentRender,
    logMetrics,
    getMemoryUsage
  }
}